home *** CD-ROM | disk | FTP | other *** search
- /*
- June 15, 1994 - KF5MG - Jack Snodgrass
-
- This code was adapted/copied from the SAM.C code. The code to process
- the QRZ disk was taken from the QRZ CD-ROM. This code could work
- with the name and zipcode versions of the Callbook data, but as-is, it
- only processes callsigns.
- */
- #include "global.h"
- #ifdef QRZCALLB
- #include "ctype.h"
-
- #define RECLEN 200
- #include "mbuf.h"
- #include "socket.h"
- #ifndef MSDOS
- #include "session.h"
- #else
- #include "hardware.h"
- #endif
-
- #if !defined(_lint)
- static char rcsid[] OPTIONAL = "$Id: qrz.c,v 1.15 1997/07/31 00:44:20 root Exp root $";
- #endif
-
- int cb_lookup (int s,char *,FILE *);
-
- /* does the actual lookup. */
- static int qrzfind(char *,int s, FILE *);
- /* Parse QRZ data record. */
- static void parse_record(char *, int s);
- /* Format QRZ Database Date. */
- static void formatdate(char *);
- /* Scan a QRZ record for the next field */
- static char *scan_field(char *cp, char fieldbuf[], int fieldlen);
-
- /* Gobal variables. */
- static char pretty_date[12];
- static char prettycall[7];
- static char *qrzdir = NULLCHAR;
- static char *qrzdrv = NULLCHAR;
-
- /* Taken from the QRZ CD-ROM disk.
- * This block is located at the start of each index
- */
- /*
- * New Index Header Block Definition
- */
- typedef struct {
- char dataname[16]; /* Name of the data file */
- char bytesperkey[8]; /* Data Bytes per Index Item */
- char numkeys[8]; /* Number of items in this index */
- char keylen[8]; /* Length of each key item in bytes */
- #ifndef _lint
- char version[8]; /* Database Version ID */
- #endif
- } index_header;
-
- /*
- * Old Index Header Block Definition
- */
- typedef struct {
- #ifndef _lint
- char dataname[13]; /* Name of the data file */
- #endif
- long bytesperkey; /* Data Bytes per Index Item */
- int numkeys; /* Number of items in this index */
- int keylen; /* Length of each key item in bytes */
- } old_index_header;
-
- /* return values - 2= Callbook Error 1= not found, 0= okay */
- int cb_lookup(s, str, fp)
- int s;
- char *str;
- FILE *fp;
- {
- if(qrzfind(str,s,fp)) {
- return 0;
- } else {
- usprintf(s,"\n No data found for %s.\n", prettycall);
- return 1;
- }
- }
-
- /*lint -esym(550,numkeys) */
- static int qrzfind(char *call_in, int s, FILE *fpout OPTIONAL)
- {
- index_header idxhdr;
- old_index_header oldidxhdr;
-
- FILE *fp;
- char *buf;
- char *bufptr;
- char IndexFile[] = "callbkc.idx";
- int size;
- int bytesperkey; /* Data Bytes per Index Item */
- int numkeys; /* Number of items in this index */
- int keylen; /* Length of each key item in bytes */
- int slots;
- int i,j,k,found,slotcnt;
- int workbufsize; /* bytesperkey + fudge */
- long fpos;
- long frc;
- char temp[255];
- char call[8];
-
-
- /* call needs to be blank filled. */
- strcpy(call," ");
-
- /* Pretty call holds the original, un-qrz-formatted callsign. */
- strcpy(prettycall, call_in);
- (void) strupr(prettycall);
-
-
- k = (int) strlen(call_in);
- if (k>6) {
- usprintf(s,"Callsign too long.\n");
- return 0;
- }
-
- /* Callsigns in the QRZ Index are stored in a weird format. They are */
- /* 6 characters in length ( padded with spaces ), in the format of */
- /* ccdccc where the digit is always in the 3rd posistion. If the */
- /* callsign is a 1-by-something callsign, the 2nd posistion will be */
- /* blank. KF5MG will be stored as KF5MGb. N5VGC will be stored as */
- /* Nb5VGC. ( the b are spaces ) */
- /* */
- call[0] = call_in[0];
- i = j = 1;
- if(!isdigit(call_in[j]))
- call[i++] = call_in[j++];
- else
- call[i++] = ' ';
- if(isdigit(call_in[j])) {
- call[i++] = call_in[j++];
- } else {
- /* No digit found in position 2 or 3. */
- usprintf(s,"Error parsing callsign... %s\n", call_in);
- return 0;
- }
- for ( ; j < (int)strlen(call_in); j++)
- call[i++] = call_in[j];
- call[6]=0;
- (void) strupr(call);
-
-
- /* Get path info. Use defaults if not available. */
- if (qrzdir == NULLCHAR) {
- if((qrzdir = getenv("QRZPATH")) == NULLCHAR) {
- #ifdef UNIX
- qrzdir = strdup("/callbk");
- #else
- qrzdir = strdup("\\callbk");
- #endif
- }
- } /* endif */
- if (qrzdrv == NULLCHAR) {
- if((qrzdrv = getenv("QRZDRV")) == NULLCHAR) {
- #ifdef UNIX
- qrzdrv = strdup("/nos");
- #else
- qrzdrv = strdup("D:");
- #endif
- }
- } /* endif */
-
- /* Open the index file. We'll use it to tell us the name of the */
- /* database file. We'll also find the database version and some */
- /* other useful info. */
- /* */
- #ifdef UNIX
- sprintf(temp,"%s%s/%s",qrzdrv,qrzdir,IndexFile);
- #else
- sprintf(temp,"%s%s\\%s",qrzdrv,qrzdir,IndexFile);
- #endif
- if((fp = fopen(temp,"rt"))==NULLFILE) {
- usprintf(s,"Error opening Index: %s\n",temp);
- return 0;
- }
-
- size = (int) fread(&idxhdr,sizeof(idxhdr),1,fp);
- if(size != 1) {
- usprintf(s,"Error reading Index Header.\n");
- (void) fclose(fp);
- return 0;
- }
-
- /* Old Style Index has a '0' at pos 16 and 17. - this is SUPPOSE to be valid !?!? */
- if((int)idxhdr.dataname[16] != 0) { /*lint !e415 */
- /* This is a 'new' style index */
- bytesperkey = atoi(idxhdr.bytesperkey); /* size of data area. */
- numkeys = atoi(idxhdr.numkeys); /* # of keys in file. */
- keylen = atoi(idxhdr.keylen); /* length of each key. */
- } else {
- /* This is an 'old' style index. */
- /* rewind the file and read the header using the old_index_header struct. */
- rewind(fp);
-
- size = (int) fread(&oldidxhdr,sizeof(oldidxhdr),1,fp);
- if(size != 1) {
- usprintf(s,"Error reading Index Header.\n");
- (void) fclose(fp);
- return 0;
- }
- bytesperkey = (int)oldidxhdr.bytesperkey; /* size of data area. */
- numkeys = oldidxhdr.numkeys; /* # of keys in file. */
- keylen = oldidxhdr.keylen; /* length of each key. */
- }
-
- /* This is a 10K ish buffer. Each 'key' in the index covers almost */
- /* 10K of data. Once you find the correct key, you have to read the */
- /* 10K chunk of data from the data file. You then start searching */
- /* for the correct callsign. This code uses the same 10k buffer to */
- /* scan the index file ( typically 40K so you might do 4 reads ) to */
- /* save memory. Once you've found the correct key, you calculate the */
- /* offset into the database. You then read the data base into your */
- /* 10K buffer. (We fudge bytesperkey by RECLEN to avoid a truncated */
- /* last record in the buffer). */
- /* */
- workbufsize = bytesperkey+RECLEN;
- bufptr = mallocw((unsigned) workbufsize); /* Get space for buffer */
- if (bufptr == NULL) { /* no space */
- usprintf(s,"No space for %d byte buffer.\n",workbufsize);
- (void) fclose(fp);
- return(0);
- }
-
- slots = bytesperkey / keylen; /* Calculate # of slots */
- found = 0;
- slotcnt = 0;
-
- do {
- /* Point floating buf pointer to start of big buffer. */
- buf = bufptr;
- /* Read slots number of entries that are keylen in size */
- size = (int) fread(buf,(unsigned) keylen, (unsigned) slots,fp);
- if(size == 0) {
- usprintf(s,"Error reading Index file.\n");
- found = 2;
- }
-
- /* Start scanning Index buffer. If the data is less than your search */
- /* Value... keep going. If the Data is greater, then your done. You */
- /* then subtract one from your slotcnt (unless it's an exact match) */
- /* and that's the closet record to your data. */
- /* */
- for(i=0;i<size;i++) {
- slotcnt++;
- strncpy(temp,(char *)buf, (unsigned) keylen);
- temp[keylen] = 0;
- if(strncmp(&temp[3],&call[3],3) >= 0) {
- if(strncmp(&temp[3],&call[3],3) > 0) {
- found = 1;
- slotcnt--;
- }
- else { /* last 3 equal. How about digit? */
- if(strncmp(&temp[2],&call[2],1) >= 0) {
- if(strncmp(&temp[2],&call[2],1) > 0) {
- slotcnt--;
- found = 1;
- }
- else /* digits are equal. Check first 2 chars */
- if(strncmp(&temp[0],&call[0],2) > 0) {
- slotcnt--;
- found = 1;
- }
- }
- }
- }
- if(found)
- break;
- buf += keylen;
- }
- } while(!found); /* enddo */
-
- slotcnt--;
-
- /* We're done with the Index so we can close it. */
- (void) fclose(fp);
-
- /* If we found a match, the calculate the offset and read the data. */
- if(found == 1) {
- buf = bufptr;
- #ifdef UNIX
- sprintf(temp,"%s%s/%s",qrzdrv,qrzdir,idxhdr.dataname);
- #else
- sprintf(temp,"%s%s\\%s",qrzdrv,qrzdir,idxhdr.dataname);
- #endif
- if((fp = fopen(temp,"rt"))==NULLFILE) {
- usprintf(s,"Error opening Database: %s\n",temp);
- free(bufptr);
- return 0;
- }
-
- /* seek to correct posistion in file . */
- fpos = (long) bytesperkey*slotcnt;
-
- frc = lseek(fileno(fp),(long) fpos,SEEK_SET);
- if(frc < 0L) {
- usprintf(s,"Error seeking Database file.\n");
- free(bufptr);
- (void) fclose(fp);
- return 0;
- }
-
- /* Read slot from callbk file. */
- size = (int) fread(buf, (unsigned) workbufsize,1,fp);
- if(size < 1) {
- usprintf(s,"Error reading Database file.\n");
- free(bufptr);
- (void) fclose(fp);
- return 0;
- }
-
- /* Done with data file. Now we can close it too. Our target is either */
- /* in our buffer or doesn't exist. */
- (void) fclose(fp);
-
- i = 0;
- for(;;) {
- if(i>workbufsize) {
- found = 0;
- break;
- }
- k = (int) strcspn(buf,"\n");
- if(k == 0) {
- found = 0;
- break;
- }
- strncpy(temp,buf, (unsigned) k);
- temp[k] = 0;
- for(j=0;j<=k;j++)
- buf += 1;
-
- /* Find our user. */
- if(strncmp(temp,call,6) == 0) {
- /* Found it. Now read and format the data. */
- parse_record(temp,s);
- break;
- }
- i+=k;
- }
- }
- /* Done with the buffer. */
- free(bufptr);
- return found;
- }
-
- static char *
- scan_field(char *cp, char fieldbuf[], int fieldlen)
- {
- char *cp1;
-
- cp1 = strchr(cp, ',');
- if (cp1) {
- *cp1++ = 0;
- strncpy(fieldbuf, cp, (unsigned) fieldlen);
- fieldbuf[fieldlen-1] = 0;
- cp=cp1;
- }
- else fieldbuf[0]=0;
- return(cp);
- }
-
- static void parse_record(char *record, int s) {
- /*
- * Standard Record Format
- */
- char callsign[7]; /* Call Sign Decoded */
- char lastname[33]; /* Last Name */
- char namesuffix[3]; /* Name Suffix */
- char frstname[33]; /* First Name */
- char middleinit[3]; /* Middle Initial */
- char datelicensed[6]; /* Date Licensed mm/dd/yy */
- char dateborn[6]; /* Date Born */
- char dateexpires[6]; /* Date Born */
- char streetaddr[33]; /* Street Address */
- char city[33]; /* City */
- char state[3]; /* State Code */
- char zipcode[6]; /* Zip Code */
- char license_class[3]; /* License Class */
- char prevcall[7]; /* Previous Call */
- char prevclass[3]; /* Previous Class */
-
- char *cp;
- char fullname[80];
- char address[80];
- char temp2[255];
-
- int rc;
-
- #ifdef QRZDEBUG
- usprintf(s, "debug: %s\n", record);
- #endif
- strcpy(temp2,record);
- cp=temp2;
- cp = scan_field(cp, callsign, sizeof(callsign));
-
- if(strlen(record) < 16) {
- usprintf(s,"%s is an old call for %s\n", prettycall, cp);
- rc = cb_lookup(s,cp,(FILE *) 0);
- if(rc != 0)
- usprintf(s,"no info found for %s.\n", cp);
- return;
- }
-
- cp = scan_field(cp, lastname, sizeof(lastname));
-
- cp = scan_field(cp, namesuffix, sizeof(namesuffix));
-
- cp = scan_field(cp, frstname, sizeof(frstname));
-
- cp = scan_field(cp, middleinit, sizeof(middleinit));
-
- cp = scan_field(cp, dateborn, sizeof(dateborn));
-
- cp = scan_field(cp, datelicensed, sizeof(datelicensed));
-
- cp = scan_field(cp, dateexpires, sizeof(dateexpires));
-
- cp = scan_field(cp, streetaddr, sizeof(streetaddr));
-
- cp = scan_field(cp, city, sizeof(city));
-
- cp = scan_field(cp, state, sizeof(state));
-
- cp = scan_field(cp, zipcode, sizeof(zipcode));
-
- cp = scan_field(cp, license_class, sizeof(license_class));
-
- cp = scan_field(cp, prevcall, sizeof(prevcall));
-
- cp = scan_field(cp, prevclass, sizeof(prevclass));
-
- sprintf(fullname,"%s%s%s%s%s%s%s",frstname, middleinit[0] == 0 ? "":" ",middleinit,
- middleinit[0] == 0 ? " ":". ", lastname, namesuffix[0] == 0 ? " ":", ", namesuffix);
- sprintf(address, "%s, %s, %s", city, state, zipcode);
-
- usprintf(s,"\n%-8s", prettycall);
- usprintf(s,"%-45s", fullname);
- formatdate(dateborn);
- usprintf(s,"Born: %s\n", pretty_date);
-
- usprintf(s,"%-8s%-45s","", streetaddr);
- formatdate(datelicensed);
- usprintf(s,"Class: %s %s\n", (license_class[0]?license_class:"r"), pretty_date);
-
- usprintf(s,"%-8s%-45s", "", address);
- usprintf(s,"Prev: %s %s\n", prevclass, prevcall);
-
- formatdate(dateexpires);
- usprintf(s,"%52s Expir: %s\n", "", pretty_date);
-
- return;
- }
-
- static void formatdate(char *date){
- char year[5];
- char rest[4];
- int mon = 0;
- int day = 0;
- int days;
- int years;
- int i;
-
- int dayarray[13] = { 0, 31, 60, 91, 121, 152, 182, /* 0 permits handling 00000 better */
- 213, 244, 274, 305, 335, 366 };
-
- strncpy(year,date,2);
- year[2] = 0;
- years = atoi(year);
- #ifdef notdef
- if(years < 20) /* fails for DOB, where 15 => 1915. -- n5knx */
- years += 2000;
- else
- years += 1900;
- #endif
-
- strncpy(rest,&date[2],3);
- rest[3] = 0;
- days = atoi(rest);
-
- if((years % 4) != 0) /* fails in 2100 */
- if(days > 59)
- days++;
-
- for(i=1;i<13;i++){
- if(days <= dayarray[i]) {
- mon = i;
- day = days - dayarray[i-1];
- break;
- }
- }
- sprintf(pretty_date, "%02d/%02d/%02d", mon,day,years);
- }
- #endif
-